import { onUnmounted } from 'vue'

type TimerType = 'interval' | 'timeout'
type TimerCallback = () => void

export class MUseTimerManager {
  static instance: MUseTimerManager | null = null
  timerRecord: Record<string, any> = {}

  constructor() {
    if (!MUseTimerManager.instance) {
      MUseTimerManager.instance = this
    }

    return MUseTimerManager.instance
  }

  /**
   * 清除定时器
   * @param key 定时器的唯一标识
   * @param type 定时器类型，默认为 'timeout'
   */
  clearTimer(key: string, type: TimerType = 'timeout') {
    const target = this.timerRecord[key]

    if (target && type === 'timeout') {
      clearTimeout(target)
    } else if (target && type === 'interval') {
      clearInterval(target)
    }

    delete this.timerRecord[key]
  }

  /**
   * 设置 setTimeout 定时器
   * @param key 定时器的唯一标识
   * @param fn 回调函数
   * @param time 延迟时间
   * @returns 定时器 ID
   */
  setTimeout(key: string, fn: TimerCallback, time: number) {
    this.clearTimer(key, 'timeout')

    try {
      const timer = window.setTimeout(fn, time)
      this.timerRecord[key] = timer
      return timer
    } catch (e) {
      console.error(`创建 setTimeout 定时器失败 ${e}`)
      return -1
    }
  }

  /**
   * 设置 setInterval 定时器
   * @param key 定时器的唯一标识
   * @param fn 回调函数
   * @param time 间隔时间
   * @returns 定时器 ID
   */
  setInterval(key: string, fn: TimerCallback, time: number) {
    this.clearTimer(key, 'interval')

    try {
      const timer = window.setInterval(fn, time)
      this.timerRecord[key] = timer
      return timer
    } catch (e) {
      console.error(`创建 setInterval 定时器失败 ${e}`)
      return -1
    }
  }
}

export const useTimer = () => {
  const timerManager = new MUseTimerManager()

  const unmountedDestroyTimer = (key: string, type: TimerType) => {
    onUnmounted(() => timerManager.clearTimer(key, type))
  }

  /**
   * 设置 setTimeout 定时器
   * @param key 定时器的唯一标识
   * @param fn 回调函数
   * @param time 延迟时间
   * @param isDestroyClear 是否在组件卸载时清除定时器，默认为 true
   */
  const setTimeoutM = (key: string, fn: TimerCallback, time: number, isDestroyClear = true) => {
    timerManager.setTimeout(key, fn, time)
    unmountedDestroyTimer(key, 'timeout')
  }

  /**
   * 设置 setInterval 定时器
   * @param key 定时器的唯一标识
   * @param fn 回调函数
   * @param time 间隔时间
   * @param isDestroyClear 是否在组件卸载时清除定时器，默认为 true
   */
  const setIntervalM = (key: string, fn: TimerCallback, time: number, isDestroyClear = true) => {
    timerManager.setInterval(key, fn, time)
    unmountedDestroyTimer(key, 'interval')
  }

  return {
    setTimeoutM,
    setIntervalM
  }
}
